package cc.rengu.igas.mcps.core.service.trans.cardpay;

import cc.rengu.igas.channel.cups.common.constant.CupsConfigConstant;
import cc.rengu.igas.channel.cups.facade.bean.CupsTermInfo;
import cc.rengu.igas.channel.cups.facade.request.ConsumeRequest;
import cc.rengu.igas.channel.cups.facade.response.ConsumeResponse;
import cc.rengu.igas.mcps.common.constant.McpsParamConstant;
import cc.rengu.igas.mcps.common.constant.McpsTreeNodeConstant;
import cc.rengu.igas.mcps.common.enums.McpsAcctTypeEnum;
import cc.rengu.igas.mcps.common.enums.RespCodeEnum;
import cc.rengu.igas.mcps.core.model.AcctAndFeeType;
import cc.rengu.igas.mcps.core.model.PosTransInfo;
import cc.rengu.igas.mcps.core.realize.EsbRealSttlePaymentService;
import cc.rengu.igas.mcps.core.realize.PosParamDealService;
import cc.rengu.igas.mcps.core.realize.impl.EsbRealSttlePaymentServiceImpl;
import cc.rengu.igas.mcps.core.realize.impl.PosParamDealServiceImpl;
import cc.rengu.igas.mcps.core.service.base.PayService;
import cc.rengu.igas.mcps.facade.base.Header;
import cc.rengu.igas.mcps.facade.request.PosCardConsumeRequest;
import cc.rengu.igas.mcps.facade.response.PosCardConsumeResponse;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.dao.RoleAcctInfoMapper;
import cc.rengu.igas.share.common.dao.impl.RoleAcctInfoMapperImpl;
import cc.rengu.igas.share.common.entity.RoleAcctInfo;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntFeeInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.MchntTermInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

//银行卡消费
public class PosCardConsumeService extends PayService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        PosCardConsumeRequest posCardComsumeReq = new PosCardConsumeRequest();
        ConvertUtil.convertOutput(posCardComsumeReq);
        return posCardComsumeReq;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        BizResponse bizResponse = new BizResponse();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String newPin = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.PIN_DATA);
        /*初始化请求对象*/
        PosCardConsumeRequest posCardComsumeReq = (PosCardConsumeRequest) request;
        /*获取机构号*/
        String instId = posCardComsumeReq.getHeader().getInstId();
        /*初始化返回报文*/
        PosCardConsumeResponse posCardComsumeRsp = new PosCardConsumeResponse();
        //TODO 待修改
        Header header = new Header();
        BeanUtil.beanCopy(posCardComsumeReq.getHeader(), header);
        posCardComsumeRsp.setHeader(header);
        posCardComsumeRsp.setPayId(sysSeqNum);
        /*获取账户类型与费率类型*/
        AcctAndFeeType acctAndFeeType = (AcctAndFeeType) xmlTreeUtil.getXmlTreeObjectValue(McpsTreeNodeConstant.ACCT_AND_FEE_TYPE, AcctAndFeeType.class);
        /*获取商户基本信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(instId, posCardComsumeReq.getMchntNo());
        if (null == mchntInfo) {
            rglog.error("查询商户基本信息失败<{}>", posCardComsumeReq.getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        //初始化用户订单表
        UserOrderInfo userOrderInfo = initOrderInfoUser(posCardComsumeReq);
        //初始化商户订单表
        MchntFeeInfo mchntFeeInfo = (MchntFeeInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.MCHNT_FEE_INFO);
        rglog.debug("费率信息：<{}>", JSON.toJSONString(mchntFeeInfo));
        MchntOrderInfo mchntOrderInfo = initOrderInfoMchnt(posCardComsumeReq, userOrderInfo, acctAndFeeType, mchntFeeInfo);
        List<MchntOrderInfo> listMchntOrderInfo = new ArrayList<>();
        listMchntOrderInfo.add(mchntOrderInfo);
        MchntTermInfo mchntTermInfo = mchntService.getMchntTermInfo(instId, posCardComsumeReq.getMchntNo(), posCardComsumeReq.getTermNo());
        PosParamDealService posParamDealService = new PosParamDealServiceImpl();
        String referenceNo = posParamDealService.getRefNo();
        posCardComsumeRsp.setReferenceNo(referenceNo);
        /*初始化支付通道订单*/
        PayOrderInfo payOrderInfoConsume = initPayOrderInfoConsume(userOrderInfo, posCardComsumeReq, acctAndFeeType.getAcctType(), posParamDealService, referenceNo);
        /*初始化订单服务*/
        OrderService orderService = new OrderServiceImpl();
        /*注册订单*/
        if (!orderService.registerOrderInfo(userOrderInfo, listMchntOrderInfo, payOrderInfoConsume)) {
            throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
        } else {
            rglog.info("订单创建成功");
        }

        //本行借记卡调核心接口
        if (McpsAcctTypeEnum.OWN_DEBIT.getAcctType().equals(acctAndFeeType.getAcctType())) {
            coreConsume(posCardComsumeReq, newPin, userOrderInfo, mchntOrderInfo, payOrderInfoConsume, posParamDealService);
        }
        //本行贷记卡调用银数接口
        if (McpsAcctTypeEnum.OWN_CREDIT.getAcctType().equals(acctAndFeeType.getAcctType())) {
            updcConsume(posCardComsumeReq, newPin, userOrderInfo, mchntOrderInfo, payOrderInfoConsume, posParamDealService);
        }
        //他行卡
        if (McpsAcctTypeEnum.OTHER_DEBIT.getAcctType().equals(acctAndFeeType.getAcctType()) || McpsAcctTypeEnum.OTHER_CREDIT.getAcctType().equals(acctAndFeeType.getAcctType())) {
            otherConsume(posCardComsumeReq, newPin, userOrderInfo, mchntOrderInfo, payOrderInfoConsume, acctAndFeeType.getAcctType(), posParamDealService, mchntTermInfo, posCardComsumeRsp);
        }
        /*特殊费率商户交易成功后调用微信进行消息推送*/
        if ("0".equals(mchntFeeInfo.getFeeInputMode()) && TransStatusEnum.TRANS_SUCC.getStatus().equals(payOrderInfoConsume.getTransStatus()) && BizStatusEnum.FINISH.getStatus().equals(payOrderInfoConsume.getBizStatus())) {
            GlobalTransUtil.setCacheValue(TransCacheConstant.USER_ORDER_INFO, userOrderInfo);
            int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != iReturnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
        }
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        bizResponse.setRespCode(posCardComsumeRsp.getRespCode());
        bizResponse.setRespDesc(posCardComsumeRsp.getRespDesc());
        bizResponse.setResult(posCardComsumeRsp);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        PosCardConsumeResponse posCardComsumeRsp = (PosCardConsumeResponse) bizResponse.getResult();
        posCardComsumeRsp.setRespCode(bizResponse.getRespCode());
        posCardComsumeRsp.setRespDesc(bizResponse.getRespDesc());
        ConvertUtil.convertInput(posCardComsumeRsp);
    }

    /**
     * 注册支付订单表
     *
     * @param posCardConsumeRequest 请求信息
     * @throws Exception 异常
     */
    private PayOrderInfo initPayOrderInfoConsume(UserOrderInfo userOrderInfo, PosCardConsumeRequest posCardConsumeRequest, String acctType, PosParamDealService posParamDealService, String referenceNo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /* 登记支付订单信息 */
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        String bizType = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE);
        /*获取本行内部渠道户*/
        RoleAcctInfoMapper roleAcctInfoMapper = new RoleAcctInfoMapperImpl();
        RoleAcctInfo roleAcctInfo = new RoleAcctInfo();
        /*区分 本他行 获取本行渠道户 或者 银联渠道户*/
        if (McpsAcctTypeEnum.OTHER_DEBIT.getAcctType().equals(acctType) || McpsAcctTypeEnum.OTHER_CREDIT.getAcctType().equals(acctType)) {
            /*银联渠道户*/
            roleAcctInfo = roleAcctInfoMapper.selectBankRoleAcctInfoBySettleAcctId(instId, "CUPS_PAYCHNL_SUBJECT", instId + McpsParamConstant.DEFAULT_TOP_INST_ID);
        } else {
            /*本行内部渠道户*/
            roleAcctInfo = roleAcctInfoMapper.selectBankRoleAcctInfoBySettleAcctId(instId, "BANK_PAYCHNL_SUBJECT", instId + McpsParamConstant.DEFAULT_TOP_INST_ID);
        }
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        payOrderInfo.setInstId(instId);
        payOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_DATE));
        payOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_TIME));
        payOrderInfo.setTxnNum(txnNum);
        payOrderInfo.setBizType(bizType);
        /*设置通到序号*/
        String strIndex = xmlTreeUtil.getXmlTreeStringValue("currentDstCallIndex");
        Integer acctCallIndex = new Integer((StringUtil.isEmptyOrNull(strIndex)) ? "0" : strIndex);
        String dstAcctCallIndex = Integer.toString(acctCallIndex + 1);
        payOrderInfo.setDstCallIndex(acctCallIndex.toString());
        xmlTreeUtil.setXmlTreeStringValue("currentDstCallIndex", dstAcctCallIndex);
        payOrderInfo.setSysSeqNum(sysSeqNum);
        //TODO 待修改
        payOrderInfo.setMchntOrderId(sysSeqNum);
        payOrderInfo.setOrderCcy(AppParamConstant.DEFAULT_ORDER_CCY);
        payOrderInfo.setOrderAmt(userOrderInfo.getOrderAmt());
        if (null != userOrderInfo.getRealPayAmt()) {
            payOrderInfo.setRealPayAmt(userOrderInfo.getRealPayAmt());
        } else {
            payOrderInfo.setRealPayAmt(userOrderInfo.getOrderAmt());
        }
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setMchntNo(posCardConsumeRequest.getMchntNo());
        payOrderInfo.setChannelOrderId(GlobalEsbUtil.generateEsbSeqeuenceNumber(instId));
        /*通道标示*/
        payOrderInfo.setMsgDstId(ChannelEnum.CUPS.getChannelType());
        if (McpsAcctTypeEnum.OWN_DEBIT.getAcctType().equals(acctType)) {
            /*支付方式*/
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            /*对账唯一key*/
            payOrderInfo.setChannelReconKey(payOrderInfo.getChannelOrderId());
            /*批次号*/
            //TODO 待修改
//            payOrderInfo.setTransBatchNo(posCardConsumeRequest.getVoucherId());
            /*通道交易码*/
            payOrderInfo.setDstTxnNum("00010000544000");
        } else if (McpsAcctTypeEnum.OWN_CREDIT.getAcctType().equals(acctType)) {
            /*子系统编号*/
            payOrderInfo.setChannelBizType("0000");
            /*支付方式*/
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            /*对账唯一key*/
            payOrderInfo.setChannelReconKey(payOrderInfo.getChannelOrderId());
            /*通道交易码*/
            payOrderInfo.setDstTxnNum("00260010508800");
        } else if (McpsAcctTypeEnum.OTHER_DEBIT.getAcctType().equals(acctType) || McpsAcctTypeEnum.OTHER_CREDIT.getAcctType().equals(acctType)) {
            /*通道类型*/
            payOrderInfo.setDstChannelType(ChannelEnum.CUPS.getChannelType());
            /*支付方式*/
            payOrderInfo.setPayType(PayTypeEnum.OTHER_BANK_CARD.getPayType());
            /*对账唯一key*/
            payOrderInfo.setChannelReconKey(posParamDealService.getCupsReconKey(instId, posCardConsumeRequest.getMchntNo()));
            ChannelCallCfg channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item -> ChannelEnum.CUPS.getChannelType().equals(item.getCallChannelId())).collect(Collectors.toList()).get(0);
            /*通道交易码*/
            payOrderInfo.setDstTxnNum(channelCallCfgList.getCallChannelTxn());
        }
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        payOrderInfo.setPayerAcctInfo(posCardConsumeRequest.getPayAcctNo());
        payOrderInfo.setPayerAcctType(acctType);
        PosTransInfo posTransInfo = new PosTransInfo();
        BeanUtil.beanCopy(posCardConsumeRequest, posTransInfo);
        posTransInfo.setRefNo(referenceNo);
        payOrderInfo.setPayerRemark(Base64.encodeBase64String(JSONObject.toJSONString(posTransInfo).getBytes()));

        if (null != roleAcctInfo) {
            payOrderInfo.setPayeeAcctInfo(roleAcctInfo.getActualAcct());
        }

        return payOrderInfo;
    }

    /**
     * 初始化商户订单表
     *
     * @param posCardConsumeRequest 请求信息
     * @throws Exception 异常
     */
    private MchntOrderInfo initOrderInfoMchnt(PosCardConsumeRequest posCardConsumeRequest, UserOrderInfo userOrderInfo, AcctAndFeeType acctAndFeeType, MchntFeeInfo mchntFeeInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        /*获取商户基本信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(posCardConsumeRequest.getHeader().getInstId(), posCardConsumeRequest.getMchntNo());
        if (null == mchntInfo) {
            rglog.error("查询商户基本信息失败<{}>", posCardConsumeRequest.getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        MchntOrderInfo mchntOrderInfo = new MchntOrderInfo();

        /*内部树复制会把订单状态保存到商户订单信息表*/
        BeanUtil.beanCopy(userOrderInfo, mchntOrderInfo);
        /*设置操作员id*/
        mchntOrderInfo.setUserId(null);
        /*设置商户订单表中业务产品代码*/
        mchntOrderInfo.setBizProdCode(txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        //商户订单号

        mchntOrderInfo.setMchntOrderId(sysSeqNum);
        /*收单机构号 */
        mchntOrderInfo.setAcqInstCode(mchntInfo.getSignInstId());
        /*行业类别*/
        mchntOrderInfo.setIndustryType(mchntInfo.getIndustryType());
        /*商户号*/
        mchntOrderInfo.setMchntNo(posCardConsumeRequest.getMchntNo());
        /*若存在 设置连锁商户门店*/
        if (null != mchntInfo.getChainMchntNo()) {
            mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
        }
        /*商户名称*/
        mchntOrderInfo.setMchntName(mchntInfo.getMchntName());
        /*交易金额*/
        mchntOrderInfo.setRealSettleAmt(posCardConsumeRequest.getTransAmt());
        mchntOrderInfo.setRealSettleFlag("N");
        /*创建时间*/
        mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        /*终端号*/
        mchntOrderInfo.setTermNo(posCardConsumeRequest.getTermNo());
        mchntOrderInfo.setRefundFee("0.00");
        mchntOrderInfo.setRefundAmt("0.00");

        // 获取费率信息
        /*更新手续费收取方式*/
        mchntOrderInfo.setFeeInputMode(mchntFeeInfo.getFeeInputMode());
        //非特殊费率商户
        if (!"0".equals(mchntFeeInfo.getFeeInputMode())) {
            /*调用手续费计算接口*/
            rglog.debug("手续费计算数据instId:<{}>,mchntNo<{}>,amount:<{}>,bizprodCode<{}>,feeType:<{}>,stageCode:<{}>,stageNum:<{}>", userOrderInfo.getInstId(), posCardConsumeRequest.getMchntNo(), mchntOrderInfo.getRealSettleAmt(), txnInfo.getSrcTxnAuthCfg().getBizProdCode(), acctAndFeeType.getFeeType(), null, null);
            boolean calcResult = mchntService.calcMchntFee(mchntOrderInfo, acctAndFeeType.getFeeType());
            //mod by lizhangtao 由于商户费率信息表中不同的产品存以下三种组合：全特殊费率，全非特殊费率，特殊和非特殊都存在；
            // 且计算手续费时只要存在特殊费率（不管是不是当前产品的）都不实时计算手续费
            // 失败：
            //   1. 返回为空 ||
            //   2. 该商户计算手续费应答中认为非特殊费率商户（全都是非特殊费率），但是没有手续费
            // 成功：(除以上失败)
            //   返回对象非空 && ((返回的FeeInputMode为0 && 无手续费) || (返回的FeeInputMode为非0 && 有手续费))
            if (!calcResult ||
                    (!"0".equals(mchntOrderInfo.getFeeInputMode()) &&
                            null == mchntOrderInfo.getMchntFee())) {
                rglog.error("计算商户手续费失败");
                throw new BizException(RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespCode(), RespCodeEnum.CALC_MCHNT_FEE_ERROR.getRespDesc());
            }
            if ("0".equals(mchntOrderInfo.getFeeInputMode())) {
                rglog.debug("由于存在了其他产品为特殊计费，因此该商户<{}>被认为是特殊费率商户不计算手续费！！", mchntOrderInfo.getMchntNo());
                mchntOrderInfo.setMchntSettleAmt(mchntOrderInfo.getOrderAmt());
            }
        } else {
            rglog.debug("该商户<{}>是特殊费率商户不计算手续费！！", mchntOrderInfo.getMchntNo());
            mchntOrderInfo.setMchntSettleAmt(mchntOrderInfo.getOrderAmt());
        }

        /*判断是否商户实时清算方式*/
        judeRealTimClearWay(posCardConsumeRequest, mchntInfo, mchntOrderInfo, acctAndFeeType);
        return mchntOrderInfo;
    }

    /**
     * 初始化用户订单表
     *
     * @param posCardConsumeRequest 请求信息
     * @throws Exception 异常
     */
    private UserOrderInfo initOrderInfoUser(PosCardConsumeRequest posCardConsumeRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        UserOrderInfo userOrderInfo = new UserOrderInfo();
        /*获取机构号*/
        String instId = posCardConsumeRequest.getHeader().getInstId();
        /*获取交易码*/
        String txnNum = posCardConsumeRequest.getHeader().getTxnNum();
        /*获取业务细分*/
        String bizType = posCardConsumeRequest.getHeader().getBizType();
        /*获取源系统标识*/
        String msgSrcId = posCardConsumeRequest.getHeader().getSrcSysId();
        userOrderInfo.setInstId(instId);
        userOrderInfo.setTxnDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_DATE));
        userOrderInfo.setTxnTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_TIME));
        userOrderInfo.setTxnNum(txnNum);
        userOrderInfo.setBizType(bizType);
        userOrderInfo.setMsgSrcId(msgSrcId);
        userOrderInfo.setTransChannelId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_CHANNEL_ID));
        //TODO 待修改
        userOrderInfo.setUserOrderId(sysSeqNum);
        userOrderInfo.setMchntOrderId(sysSeqNum);
        userOrderInfo.setOrderDesc("银行卡消费");
        userOrderInfo.setOrderCcy(AppParamConstant.DEFAULT_ORDER_CCY);
        userOrderInfo.setSysSeqNum(sysSeqNum);
        userOrderInfo.setFrontSeqNum(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRACE_NO));
        userOrderInfo.setOrderCreateTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"));
        userOrderInfo.setOrderExpiryTime(DateUtil.getDateByTimeStamp(System.currentTimeMillis() + 5 * 60 * 1000, "yyyyMMddHHmmss"));
        userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        userOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        userOrderInfo.setOrderAmt(posCardConsumeRequest.getTransAmt());
        userOrderInfo.setUserId(posCardConsumeRequest.getPayAcctNo());
        return userOrderInfo;
    }

    /*本行借记卡 通道调用*/
    private void coreConsume(PosCardConsumeRequest posCardComsumeReq, String newPin,
                             UserOrderInfo userOrderInfo, MchntOrderInfo mchntOrderInfo,
                             PayOrderInfo payOrderInfoConsume, PosParamDealService posParamDealService) throws Exception {

        // TODO 本行借记卡消费
        // (1) 通讯级失败, 更新订单为失败, 调用营销冲正comboDealService.cancelComboPayment
        // (2) 交易超时, 更新订单为超时.
        // (3) 交易成功,更新交易支付订单交易成功,
        //      判断是否实时清算esbRealSttlePaymentService.esbRealTimeClear/esbRealSttlePaymentService.esbRealSettlePayment 或 非特殊费率商户发起虚拟账户单笔记账acctDealService.virtAcctSingleAdjust
        //      更新商户限额、终端限额、交易限额及笔数 mchntService.addTxnLimitStatis
    }

    /*本行贷记卡 通道调用*/
    private void updcConsume(PosCardConsumeRequest posCardComsumeReq, String newPin,
                             UserOrderInfo userOrderInfo, MchntOrderInfo mchntOrderInfo,
                             PayOrderInfo payOrderInfoConsume, PosParamDealService posParamDealService) throws Exception {
        // TODO 本行贷记卡消费
        // (1) 通讯级失败, 更新订单为失败, 调用营销冲正comboDealService.cancelComboPayment
        // (2) 交易超时, 更新订单为超时.
        // (3) 交易成功,更新交易支付订单交易成功,
        //      判断是否实时清算esbRealSttlePaymentService.esbRealTimeClear/esbRealSttlePaymentService.esbRealSettlePayment 或 非特殊费率商户发起虚拟账户单笔记账acctDealService.virtAcctSingleAdjust
        //      更新商户限额、终端限额、交易限额及笔数 mchntService.addTxnLimitStatis

    }

    /*他行卡 通道调用*/
    private void otherConsume(PosCardConsumeRequest posCardComsumeReq, String newPin,
                              UserOrderInfo userOrderInfo, MchntOrderInfo mchntOrderInfo,
                              PayOrderInfo payOrderInfoConsume, String acctType,
                              PosParamDealService posParamDealService, MchntTermInfo mchntTermInfo,
                              PosCardConsumeResponse posCardComsumeRsp) throws Exception {
        /*设置dubbo服务*/
        DubboService dubboService = new DubboServiceImpl();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /*初始化订单服务*/
        OrderService orderService = new OrderServiceImpl();
        /*获取商户号*/
        String mchntNo = posCardComsumeReq.getMchntNo();
        /*获取终端号*/
        String termNo = posCardComsumeReq.getTermNo();
        /*获取机构号*/
        String instId = posCardComsumeReq.getHeader().getInstId();
        /*获取系统流水号*/
        String sysNum = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.SYS_SEQ_NUM);
        /*获取商户基本信息*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntNo);
        /*准备请求报文*/
        ConsumeRequest consumeRequest = new ConsumeRequest();
        cc.rengu.igas.channel.cups.facade.base.Header header = new cc.rengu.igas.channel.cups.facade.base.Header();
        BeanUtil.beanCopy(posCardComsumeReq.getHeader(), header);
        header.setTxnNum(payOrderInfoConsume.getDstTxnNum());
        payOrderInfoConsume.setDstTxnNum(header.getTxnNum());
        header.setTraceNo(payOrderInfoConsume.getChannelOrderId());
        consumeRequest.setHeader(header);
        consumeRequest.setCupsTraceNo(sysNum.substring(sysNum.length() - 6));
        consumeRequest.setTransDateTime(payOrderInfoConsume.getTxnDate().substring(4, 8) + payOrderInfoConsume.getTxnTime());
        consumeRequest.setTermNo(termNo);
        consumeRequest.setMchntAddr(mchntInfo.getMchntBizAddr());
        consumeRequest.setMchntShortName(mchntInfo.getMchntSimpleName());
        consumeRequest.setMchntType(mchntOrderInfo.getIndustryType());
        consumeRequest.setMchntNo(payOrderInfoConsume.getMchntNo());
        consumeRequest.setCupsMchntNo(mchntInfo.getCupsMchntNo());
        String acqInstCode = posParamDealService.genCupsAcqInstCode(instId, posCardComsumeReq.getMchntNo());
        String fwdInstCode = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_FWD_INS_CODE);
        consumeRequest.setCupsInstCode(acqInstCode);
        consumeRequest.setFwdInstCode(fwdInstCode);
        consumeRequest.setOrderAmt(payOrderInfoConsume.getRealPayAmt());
        consumeRequest.setOrderCcy(McpsParamConstant.INNER_DEFAULT_ORDERCCY);
        consumeRequest.setPayAcctNo(posCardComsumeReq.getPayAcctNo());
        /*小额免密标志  密码*/
        if (StringUtil.isEmptyOrNull(newPin)) {
            rglog.debug("小额免密标志：<{}>", mchntInfo.getNoPasswordFlag());
            consumeRequest.setNoPinFlag(mchntInfo.getNoPasswordFlag());
        } else {
            consumeRequest.setNoPinFlag(mchntInfo.getNoPasswordFlag());
            consumeRequest.setPinData(newPin);
        }
        //TODO 待修改
        consumeRequest.setTrack2Data(posCardComsumeReq.getTrack2Data());
        consumeRequest.setTrack3Data(posCardComsumeReq.getTrack3Data());
        consumeRequest.setReferenceNo(posCardComsumeRsp.getReferenceNo());
        consumeRequest.setCardExpireDate(posCardComsumeReq.getCardexpireDate());
        consumeRequest.setEntryMode(posCardComsumeReq.getEntryMode());
        consumeRequest.setCardSeqNo(posCardComsumeReq.getCardSeqNo());

        /*55域 卡数据*/
        consumeRequest.setIcData(posCardComsumeReq.getIcData());

        consumeRequest.setIcConCode(posCardComsumeReq.getIcConCode());
        consumeRequest.setSecCtrlInfo(posCardComsumeReq.getTrack2Data());
        CupsTermInfo cupsTermInfo = new CupsTermInfo();
        BeanUtil.beanCopy(posCardComsumeReq.getTermInfo(), cupsTermInfo);
        if (StringUtil.isEmptyOrNull(cupsTermInfo.getDeviceType())) {
            cupsTermInfo.setDeviceType(mchntTermInfo.getTermType());
        }
        consumeRequest.setTermInfo(cupsTermInfo);
        consumeRequest.setTermRead(posCardComsumeReq.getTermRead());
        /*打印请求报文*/
        rglog.info("请求报文 consumeRequset：<{}>", JSON.toJSONString(consumeRequest));
        /*调用服务*/
        cc.rengu.igas.channel.cups.facade.result.Result<ConsumeResponse> result = (cc.rengu.igas.channel.cups.facade.result.Result<ConsumeResponse>) dubboService.callDubboService("cupsPayService", "consume", consumeRequest);
        rglog.debug("dubbo调用CUPS消费结果：{}", JSON.toJSONString(result));
        /*调用失败处理*/
        if (null == result || null == result.getResult()
                || (!McpsParamConstant.DUBBO_SUCCESS.equals(result.getResult().getRespCode())
                && !McpsParamConstant.DUBBO_OVERTIME.equals(result.getResult().getRespCode())
                && !McpsParamConstant.COMMUNICATION_OVERTIME.equals(result.getResult().getRespCode()))) {
            /*设置支付订单 订单状态*/
            payOrderInfoConsume.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            payOrderInfoConsume.setBizStatus(BizStatusEnum.FAILED.getStatus());
            /*设置商户订单 订单状态*/
            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            /*设置用户订单 订单状态*/
            userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
            if (!orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfoConsume)) {
                rglog.error("订单表更新失败");
                throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
            }
        }
        //调用成功处理
        else if (result.isSuccess() && McpsParamConstant.DUBBO_SUCCESS.equals(result.getResult().getRespCode())) {
            /*通道清算日期*/
            payOrderInfoConsume.setSettleDate(result.getResult().getSettleDate());
            //授权应答码 38域可能返回,存在则需要打印小票，返回给POS
            if (!StringUtil.isEmptyOrNull(result.getResult().getAuthCode())) {
                payOrderInfoConsume.setTxnAuthCode(result.getResult().getAuthCode());
            }
            /*设置返回码跟描述*/
            payOrderInfoConsume.setRespCode(result.getResult().getRespCode());
            payOrderInfoConsume.setRespDesc(result.getResult().getRespDesc());
            /*设置支付订单 订单状态*/
            payOrderInfoConsume.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            payOrderInfoConsume.setBizStatus(BizStatusEnum.FINISH.getStatus());
            /*设置商户订单 订单状态*/
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            /*设置用户订单 订单状态*/
            userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            /*更新*/
            if (!orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfoConsume)) {
                rglog.error("订单表更新失败");
                throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
            }
            /*插入更新后的商户订单表 到内部树*/
            xmlTreeUtil.setXmlTreeObjectValue(McpsTreeNodeConstant.MCHNT_ORDER_INFO, mchntOrderInfo);
            /*判断是否实时清算*/
            EsbRealSttlePaymentService esbRealSttlePaymentService = new EsbRealSttlePaymentServiceImpl();
            if (AppParamConstant.YES.equals(mchntOrderInfo.getRealSettleFlag())) {
                if ("00".equals(mchntOrderInfo.getRealSettleType())) {
                    esbRealSttlePaymentService.esbRealTimeClear(mchntOrderInfo, payOrderInfoConsume, posCardComsumeReq.getHeader());
                } else {
                    esbRealSttlePaymentService.esbRealSettlePayment(mchntOrderInfo, payOrderInfoConsume, posCardComsumeReq.getHeader());
                }
            }
            //更新商户限额、终端限额、交易限额及笔数
            mchntService.updateMchntTransLimit(mchntOrderInfo);
        }
        //调用超时处理
        else {
            /*设置返回码跟描述*/
            payOrderInfoConsume.setRespCode(result.getResult().getRespCode());
            payOrderInfoConsume.setRespDesc(result.getResult().getRespDesc());
            /*设置支付订单 订单状态*/
            payOrderInfoConsume.setTransStatus(TransStatusEnum.TRANS_TIMEOUT.getStatus());
            /*设置商户订单 订单状态*/
            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_TIMEOUT.getStatus());
            /*设置用户订单 订单状态*/
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_TIMEOUT.getStatus());
            if (!orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfoConsume)) {
                rglog.error("订单表更新失败");
                throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
            }
        }

        /*设置返回码 返回信息*/
        if (null == result || !result.isSuccess()) {
            posCardComsumeRsp.setRespCode(OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
            posCardComsumeRsp.setRespDesc(OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
        } else {
            posCardComsumeRsp.setRespCode(result.getResult().getRespCode());
            posCardComsumeRsp.setRespDesc(result.getResult().getRespDesc());
            posCardComsumeRsp.setPayId(sysNum);
            posCardComsumeRsp.setSettleDate(result.getResult().getSettleDate());
            posCardComsumeRsp.setIcData(result.getResult().getIcData());
            posCardComsumeRsp.setReferenceNo(consumeRequest.getReferenceNo());
            //收单机构
            posCardComsumeRsp.setAcqInstCode(consumeRequest.getCupsInstCode());
            //发卡机构
            posCardComsumeRsp.setPayAcctIssCode(result.getResult().getRcvInstCode());
            posCardComsumeRsp.setTxnDate(consumeRequest.getHeader().getTransDate());
            posCardComsumeRsp.setTxnTime(consumeRequest.getHeader().getTransTime());
            if (!StringUtil.isEmptyOrNull(result.getResult().getAuthCode())) {
                posCardComsumeRsp.setTransAuthCode(result.getResult().getAuthCode());
            }
        }
    }

    /*获取实时入账最小金额*/
    private String getRealTimeClearAmt(String instId) throws Exception {
        String paramType = "MCHNT_SERVICE";
        String paramKey = "D0_ACCOUNTING_MIN_AMT";
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(instId, paramType, paramKey);
        if (null == sysParam) {
            rglog.info("实时入账最小金额未配置,使用默认金额");
            return McpsParamConstant.DEFAULT_REAL_TIME_PAY_MIN_AMT;
        } else {
            return sysParam.getParamValue();
        }
    }

    /*判断是否商户实时清算方式*/
    private void judeRealTimClearWay(PosCardConsumeRequest posCardComsumeReq, MchntInfo mchntInfo, MchntOrderInfo mchntOrderInfo, AcctAndFeeType acctAndFeeType) throws Exception {
        /*获取结算账户信息*/
        MchntAcctInfo mchntAcctInfo = getMchntAcctInfo(posCardComsumeReq, mchntInfo);
        /* 获取实时入账最低金额*/
        String minAmt = getRealTimeClearAmt(mchntOrderInfo.getInstId());
        /*判断交易金额是否大于实时入账最低金额*/
        if (AmountUtil.compare(mchntOrderInfo.getRealSettleAmt(), minAmt) != -1) {
            /* 实时清算标识 、结算方式*/
            if ("Y".equals(mchntInfo.getRealSettleFlag()) && (McpsAcctTypeEnum.OWN_DEBIT.getAcctType().equals(acctAndFeeType.getAcctType()) || McpsAcctTypeEnum.OWN_CREDIT.getAcctType().equals(acctAndFeeType.getAcctType()))) {
                mchntOrderInfo.setRealSettleFlag("Y");
                mchntOrderInfo.setRealSettleType("00");
            } else if ("D0".equals(mchntAcctInfo.getSettleType()) && !"Y".equals(mchntInfo.getRealSettleFlag())) {
                mchntOrderInfo.setRealSettleFlag("Y");
                mchntOrderInfo.setRealSettleType("99");
            } else {
                mchntOrderInfo.setRealSettleFlag("N");
            }
        }
    }

    /*获取商户结算账户信息*/
    private MchntAcctInfo getMchntAcctInfo(PosCardConsumeRequest request, MchntInfo mchntInfo) throws Exception {
        String mchntNo = mchntInfo.getMchntNo();
        /*判断商户是否为独立清算商户*/
        if (!"Y".equals(mchntInfo.getIndependentDataFlag()) && "11".equals(mchntInfo.getMchntType())) {
            mchntNo = mchntInfo.getChainMchntNo();
        }
        MchntService mchntService = new MchntServiceImpl();
        List<MchntAcctInfo> mchntAcctInfoList = mchntService.getMchntAcctInfo(request.getHeader().getInstId(), mchntNo);
        Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getFundType().equals("00")).findFirst();
        return mchntAcctInfoOpt.orElse(null);
    }
}